package com.storlead.email.util;

import com.google.common.collect.ImmutableMap;
import com.sun.mail.imap.IMAPStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import sun.misc.resources.Messages;

import javax.mail.*;
import javax.mail.Flags.Flag;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Properties;

import static javax.mail.Flags.Flag.*;

/**
 * @Author: Timo
 * @Date: 2019/2/21 11:33
 * @Description: 类用途：
 */
@Component
public class EmailUtils {

    private static final String QQ_PASSWORD = "gshjwpkyfwkgbddg";
    private static final Logger log = LoggerFactory.getLogger(EmailUtils.class);

    @Autowired
    JavaMailSender mailSender;


    public static void main(String[] args) throws Exception {
//        exmailQqResceiveSmtp();
        qqResceiveImap();
    }

    public static void qqSendMsg() {

    }


    public static void qqResceiveImap() throws MessagingException, UnsupportedEncodingException {
        Properties props = System.getProperties();
        props.setProperty("mail.imap.host", "imap.qq.com");
        props.setProperty("mail.store.protocol", "imap");
        props.setProperty("mail.imap.port", "143");

        Session session = Session.getInstance(props);
        // 方式1
//        URLName urln = new URLName("imap", "imap.qq.com", 143, null, "1002512666@qq.com", QQ_PASSWORD);
//        Store store = session.getStore(urln);
//        store.connect();

        // 方式二
        IMAPStore store = (IMAPStore) session.getStore("imap");
        store.connect("1002512666@qq.com", QQ_PASSWORD);


        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);
        System.out.println("未读邮件数量：" + folder.getUnreadMessageCount());
        System.out.println("新邮件 数 量：" + folder.getNewMessageCount());
        System.out.println("邮件总 数 量：" + folder.getMessageCount());
        parseMessage(folder.getMessages());

    }


    public static void qqResceiveSmtp() throws MessagingException {
        Properties props = System.getProperties();
        props.setProperty("mail.smtp.host", "smtp.qq.com");
        props.setProperty("mail.smtp.port", "465");
        props.setProperty("mail.store.protocol", "smtp");

        URLName urln = new URLName("smtp", "smtp.qq.com", 993, null, "1002512666@qq.com", "gshjwpkyfwkgbddg");

        Session session = Session.getInstance(props);
        Store store = session.getStore(urln);
        store.connect();


        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);
        System.out.println("未读邮件数量：" + folder.getUnreadMessageCount());
        System.out.println("新邮件 数 量：" + folder.getNewMessageCount());
        System.out.println("邮件总 数 量：" + folder.getMessageCount());

    }


    public static void exmailQqResceiveSmtp() throws MessagingException, UnsupportedEncodingException {
        log.info("--------------------------------- 企业邮箱 获取邮件start ---------------------------");
        // 设置连接的环境变量
        Properties props = System.getProperties();
        props.setProperty("mail.imap.host", "smtp.exmail.qq.com");
        props.setProperty("mail.imap.port", "143");
        props.setProperty("mail.store.protocol", "imap");


        Session session = Session.getInstance(props);
        IMAPStore store = (IMAPStore) session.getStore("imap");
        store.connect("timo@storlead.com", "Jyx19910320.");


        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);

        log.info("------总邮件数量:{}", folder.getMessageCount());
        log.info("------未读邮件数量:{}", folder.getUnreadMessageCount());
        log.info("------新邮件的数量:{}", folder.getUnreadMessageCount());
        parseMessage(folder.getMessages());
    }

    /**
     * 设置环境变量参数
     *
     * @param email
     * @return
     */
    private static Properties getProperties(String email) {
        Properties prop = System.getProperties();
        EmailProperties emailProperties = EmailProperties.getEmailProperties(email);
        if (emailProperties != null) {
            emailProperties.prop.forEach((k, v) -> {
                prop.setProperty(k, v);
            });
        }
        return prop;
    }


    private static Store getStore(String email, String account, String password) throws MessagingException {
        Session session = Session.getInstance(getProperties(email));
        IMAPStore store = (IMAPStore) session.getStore("imap");
        store.connect(account, password);
        return store;
    }

    /**
     * 环境变量的配置
     */
    private enum EmailProperties {
        /**
         * 腾讯企业邮箱
         */
        EXMAIL_QQ("exmail_qq", ImmutableMap.of(
                "mail.store.protocol", "imap",
                "mail.smtp.host", "smtp.exmail.qq.com",
                "mail.smtp.port", "143",
                "mail.smtp.auth", "true")),
        /**
         * QQ 个人邮箱
         */
        QQ("qq", ImmutableMap.of(
                "mail.store.protocol", "imap",
                "mail.imap.host", "imap.qq.com",
                "mail.smtp.port", "143",
                "mail.smtp.auth", "true"));

        public String emailType;
        public Map<String, String> prop;

        EmailProperties(String emailType, Map<String, String> prop) {
            this.emailType = emailType;
            this.prop = prop;
        }

        /**
         * 根据邮箱类型获取 系统配置文件
         *
         * @param emailType
         * @return
         */
        public static EmailProperties getEmailProperties(String emailType) {
            for (EmailProperties p : EmailProperties.values()) {
                if (p.emailType.equals(emailType)) {
                    return p;
                }
            }
            return null;
        }
    }


    public static void parseMessage(Message... messages) throws MessagingException, UnsupportedEncodingException {
        String prefix = "----";
        log.info("--------------------- 邮件解析开始 ----------------------------");
        if (messages == null || messages.length < 1) {
            log.info("-------------- 解析邮箱解释 无邮件可以解析 ----------------------");
            return;
        }
        int msgCount = messages.length;
        log.info("{}总邮件数量：{}", prefix, msgCount);
        for (int i = msgCount - 1; i >= 0; i--) {
            MimeMessage msg = (MimeMessage) messages[i];

            log.info("--------------------第{}条--------------------", (msgCount - i));
            log.info("----{} , 邮件主题：{}", msg.getMessageID(), msg.getSubject());
            log.info("----发件人  ：{}", getFrom(msg)[0]);
            log.info("----发件邮箱：{}", getFrom(msg)[1]);
            log.info("----邮件状态：{}", msg.getFlags());
            log.info("----did：{}", msg.getContentID());

            if (i == (msgCount - 1)) {
                deleteMessage(msg);
            }
        }

    }

    /**
     * 获得邮件发件人
     */
    public static String[] getFrom(MimeMessage msg) throws MessagingException, UnsupportedEncodingException {
        String[] from = new String[2];
        Address[] froms = msg.getFrom();
        if (froms.length < 1) {
            throw new MessagingException("No find sender user!");
        }

        InternetAddress address = (InternetAddress) froms[0];
        //需要解码的话：MimeUtility.decodeText(address.getPersonal())
        from[0] = address.getPersonal();
        from[1] = address.getAddress();
        return from;
    }

    /**
     * 获取发件人的昵称
     *
     * @param msg
     * @return
     * @throws UnsupportedEncodingException
     * @throws MessagingException
     */
    public static String getReceiveEmailUserName(MimeMessage msg) throws UnsupportedEncodingException, MessagingException {
        return getFrom(msg)[0];
    }

    /**
     * 获取发件发件人的邮箱地址
     *
     * @param msg
     * @return
     * @throws UnsupportedEncodingException
     * @throws MessagingException
     */
    public static String getReceiveEmailAddress(MimeMessage msg) throws UnsupportedEncodingException, MessagingException {
        return getFrom(msg)[1];
    }

    /**
     * 删除邮件
     *
     * @param messages
     * @return
     */
    public static boolean deleteMessage(Message... messages) throws MessagingException {
        if (emailIsEmpty(messages)) {
            throw new MessagingException("not fund message");
        }
        for (Message message : messages) {
            MimeMessage mm = (MimeMessage) message;
            mm.setFlag(Flag.DELETED, true);
            log.info("Marked DELETE for message this Subject is :{} and messagesId is {}", mm.getSubject(), mm.getMessageID());
        }
        return true;
    }

    /**
     * 判断邮件消息是否为空或者是不存在
     *
     * @param messages
     * @return true 不存在 / flase 存在
     */
    private static boolean emailIsEmpty(Message... messages) {
        if (messages == null || messages.length < 0) {
            return true;
        }
        return false;
    }

    /**
     * 邮件以读
     *
     * @param messages
     * @return
     * @throws MessagingException
     */
    public static boolean readMessage(Message... messages) throws MessagingException {
        if (emailIsEmpty(messages)) {
            throw new MessagingException("not find message");
        }
        for (Message message : messages) {
            MimeMessage mm = (MimeMessage) message;
            mm.setFlag(Flag.SEEN, true);
            log.info("Marked READ for message this Subject is :{} and messagesId is {}", mm.getSubject(), mm.getMessageID());
        }
        return true;
    }

    public static void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException {
        System.out.println(part.getContentType());
        boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
        if (part.isMimeType("text/*") && !isContainTextAttach) {
            content.append(part.getContent().toString());
        } else if (part.isMimeType("message/rfc822")) {
            getMailTextContent((Part) part.getContent(), content);
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int partCount = multipart.getCount();
            for (int i = 0; i < partCount; i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                getMailTextContent(bodyPart, content);
            }
        }
    }

    /**
     * 获取接收地址
     *
     * @param msg
     * @param type
     * @return
     * @throws MessagingException
     */
    public static String getReceiveAddress(MimeMessage msg, Message.RecipientType type) throws MessagingException {
        StringBuffer receiveAddress = new StringBuffer();
        Address[] addresss = null;
        if (type == null) {
            addresss = msg.getAllRecipients();
        } else {
            addresss = msg.getRecipients(type);
        }
        if (addresss == null || addresss.length < 1) {
            throw new MessagingException("没有收件人!");
        }
        for (Address address : addresss) {
            InternetAddress internetAddress = (InternetAddress) address;
            receiveAddress.append(internetAddress.toUnicodeString()).append(",");
        }
        // 删除最后一个逗号
        receiveAddress.deleteCharAt(receiveAddress.length() - 1);
        return receiveAddress.toString();
    }

    /**
     * 获得邮件的优先级
     *
     * @return 1(High):紧急 3:普通(Normal) 5:低(Low)
     */
    public static String getPriority(MimeMessage msg) throws MessagingException {
        String priority = "普通";
        String[] headers = msg.getHeader("X-Priority");
        if (headers != null) {
            String headerPriority = headers[0];
            if (headerPriority.indexOf("1") != -1 || headerPriority.indexOf("High") != -1) {
                priority = "紧急";
            } else if (headerPriority.indexOf("5") != -1 || headerPriority.indexOf("Low") != -1) {
                priority = "低";
            } else {
                priority = "普通";
            }
        }
        return priority;
    }

    /**
     * 判断邮件中是否包含附件
     */
    public static boolean isContainAttachment(Part part) throws MessagingException, IOException {
        boolean flag = false;
        if (part.isMimeType("multipart/*")) {
            MimeMultipart multipart = (MimeMultipart) part.getContent();
            int partCount = multipart.getCount();
            for (int i = 0; i < partCount; i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                String disp = bodyPart.getDisposition();
                if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
                    flag = true;
                } else if (bodyPart.isMimeType("multipart/*")) {
                    flag = isContainAttachment(bodyPart);
                } else {
                    String contentType = bodyPart.getContentType();
                    if (contentType.indexOf("application") != -1) {
                        flag = true;
                    }
                    if (contentType.indexOf("name") != -1) {
                        flag = true;
                    }
                }
                if (flag) {
                    break;
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            flag = isContainAttachment((Part) part.getContent());
        }
        return flag;
    }
}
